﻿package	birdry.ui	{
	
	import flash.display.MovieClip;
	import flash.events.*;
	import birdry.utils.DisplayObjectUtil;
	import birdry.control.KeyManager;

	public class Move3D	extends MovieClip	{
		
		private var _mcArray:Array;	// 3D 대상 무브클립 배열
		
		private var _stageWidth:int;
		private var _stageHeight:int;
		
		private var _rotateX_value:Number;
		private var _keyCode:int;
		private var _arrayTotal:uint;
		
		private var _targetX:String;
		private var _targetY:String;
		private var _targetZ:String;
		
		private var _onKeyUp:Boolean;
		private var _onKeyDown:Boolean;
		private var _onKeyLeft:Boolean;
		private var _onKeyRight:Boolean;
		
		
		private var _userMc:MovieClip;
		
		private var _mapSizeX:uint;
		private var _mapSizeY:uint;
		
		
		var i:uint;
		
		public function Move3D(mcArray:Array, targetX:String, targetY:String, targetZ:String, mapSizeX:uint, mapSizeY:uint): void	{
			this._mcArray = mcArray;
			this._targetX = targetX;
			this._targetY = targetY;
			this._targetZ = targetZ;
			this._mapSizeX = mapSizeX;
			this._mapSizeY = mapSizeY;
			defaultSet();
			setLayout();
		}
		
		
		private function defaultSet(): void	{
			_stageWidth = _mcArray[0].stage.stageWidth;
			_stageHeight = _mcArray[0].stage.stageHeight;
			
			f = 500;
			viewPoint = 0;
			rotateLEFT_size = 0.03;
			rotateRIGHT_size = 0.03;
			rotateUP_size = 10
			rotateDOWN_size = 5
			
			_userMc = new MovieClip();
			_userMc.tx = 0;
			_userMc.ty = 0;
			_userMc.tr = 0;
		}
		
		private function setLayout(): void	{
			_rotateX_value = 0;
			_arrayTotal = _mcArray.length;
			for( i=0; i<_arrayTotal; ++i )	{
				if(_mcArray[i][_targetX] == undefined)		_mcArray[i][_targetX] = int(Math.random()*_stageWidth*3) - _stageWidth;
				if(_mcArray[i][_targetY] == undefined)		_mcArray[i][_targetY] = 0;
				if(_mcArray[i][_targetZ] == undefined)		_mcArray[i][_targetZ] = int(Math.random()*_stageWidth*3) - _stageWidth;
			}
		}
		
		private function addEvent(): void	{
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
			this._mcArray[0].stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyDown);
			this._mcArray[0].stage.addEventListener(KeyboardEvent.KEY_UP, KeyUp);
		}
		
		private function removeEvent(): void	{
			removeEventListener(Event.ENTER_FRAME, onEnterFrame);
			this._mcArray[0].stage.removeEventListener(KeyboardEvent.KEY_DOWN, KeyDown);
			this._mcArray[0].stage.removeEventListener(KeyboardEvent.KEY_UP, KeyUp);
		}
		
		
		private function KeyDown( e: KeyboardEvent ) : void	{
			if(e.keyCode == KeyManager.UP || e.keyCode == KeyManager.W)			_onKeyUp = true;
			if(e.keyCode == KeyManager.DOWN || e.keyCode == KeyManager.S)		_onKeyDown = true;
			if(e.keyCode == KeyManager.LEFT || e.keyCode == KeyManager.A)		_onKeyLeft = true;
			if(e.keyCode == KeyManager.RIGHT || e.keyCode == KeyManager.D)		_onKeyRight = true;
			addEventListener(Event.ENTER_FRAME, onKeyDowning);
		}
		
		private function KeyUp( e: KeyboardEvent ): void	{
			if(e.keyCode == KeyManager.UP || e.keyCode == KeyManager.W)			_onKeyUp = false;
			if(e.keyCode == KeyManager.DOWN || e.keyCode == KeyManager.S)		_onKeyDown = false;
			if(e.keyCode == KeyManager.LEFT || e.keyCode == KeyManager.A)		_onKeyLeft = false;
			if(e.keyCode == KeyManager.RIGHT || e.keyCode == KeyManager.D)		_onKeyRight = false;
			if(!_onKeyUp && !_onKeyDown && !_onKeyLeft && !_onKeyRight)			removeEventListener(Event.ENTER_FRAME, onKeyDowning);
			_rotateX_value = 0;
		}
		
		private function onKeyDowning( e: Event ): void	{
			var vy:int;
			if(_onKeyUp)			vy = -rotateUP_size;
			if(_onKeyDown)			vy = rotateDOWN_size;
			if(_onKeyLeft)			_rotateX_value = rotateLEFT_size;
			if(_onKeyRight)			_rotateX_value = -rotateRIGHT_size;
			
			
			
			_userMc.tr = Math.sin(1);
			trace(_userMc.tr);
			
			for( i=0; i<_arrayTotal; ++i )	{
				_mcArray[i][_targetZ] += vy;
			}
			
		}
			
		public function start(): void	{
			addEvent();
		}
		
		public override function stop(): void	{
			removeEvent();
		}
		
		private function onEnterFrame( e: Event ): void	{
			for( i=0; i<_arrayTotal; ++i )	{
				rotateX(_mcArray[i], _rotateX_value, -_f, 0);
				plot3d(_mcArray[i], _f, _viewPoint, _stageWidth, _stageHeight);
			}
			DisplayObjectUtil.depthSort(_mcArray, "tZ");
		}
		
		
		// 3D 원근 표시 메서드
		private function plot3d ( mc:MovieClip, f:int, viewPoint:int, stageWidth:int, stageHeight:int): void	{
			if(mc[_targetZ] < -f)	{
				mc.visible = false;
			}	else	{
				mc.visible = true;
				var scale:Number = f / (f + mc[_targetZ]);
				mc.scaleY = mc.scaleX = scale;
				mc.x = (stageWidth >> 1 ) + mc[_targetX] * scale;
				mc.y = (stageHeight >> 1 ) + mc[_targetY] * scale - viewPoint * mc[_targetZ];
			}
		}
		
		// x축 회전 메서드
		private function rotateX ( mc:MovieClip, t:Number, cz:int, cx:int)	{
			var tempz = cz + (mc[_targetZ] - cz) * Math.cos(t) - (mc[_targetX] - cx) * Math.sin(t);
			mc[_targetX] = cx + (mc[_targetZ] - cz) * Math.sin(t) + (mc[_targetX] - cx) * Math.cos(t);
			mc[_targetZ] = tempz;
		}
		
		
		/*************************************************************************
		* 
		* 속성값 접근 펑션
		* 
		************************************************************************/
		
		public var _f:int;	// 스크린과 눈 사이의 거리
		public var _viewPoint:int;	// 관찰자의 눈높이 설정
		private var _rotateLEFT_size:Number;
		private var _rotateRIGHT_size:Number;
		private var _rotateUP_size:Number;
		private var _rotateDOWN_size:Number;
		
		public function get f():int	{
			return _f;
		}
		public function set f( value: int ): void	{
			_f = value;
		}
		public function get viewPoint():int	{
			return _viewPoint;
		}
		public function set viewPoint( value: int ): void	{
			_viewPoint = value;
		}
		
		public function get rotateLEFT_size():Number	{
			return _rotateLEFT_size;
		}
		public function set rotateLEFT_size( value: Number ): void	{
			_rotateLEFT_size = value;
		}
		public function get rotateRIGHT_size():Number	{
			return _rotateRIGHT_size;
		}
		public function set rotateRIGHT_size( value: Number ): void	{
			_rotateRIGHT_size = value;
		}
		public function get rotateUP_size():Number	{
			return _rotateUP_size;
		}
		public function set rotateUP_size( value: Number ): void	{
			_rotateUP_size = value;
		}
		public function get rotateDOWN_size():Number	{
			return _rotateDOWN_size;
		}
		public function set rotateDOWN_size( value: Number ): void	{
			_rotateDOWN_size = value;
		}
		
	}	// class
}	// package

